<template>
  <div ref="chart" style="height: 100%"></div>
</template>
<script>
import { Chart, registerInteraction } from '@antv/g2';
import { xFormat } from '@/utils/chartDateFormatter.js';
import { computeFontSize } from '@/utils/commonFun.js';
export default {
  name: 'StackBarChart',
  props: {
    data: {
      type: Array,
      required: true
    },
    x: {
      type: String,
      default: 'x'
    },
    y: {
      type: String,
      default: 'y'
    },
    s: {
      type: String,
      default: 's'
    },
    color: {
      type: Array,
      required: true
    },
    unit: String,
    offsetX: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      chart: null
    };
  },
  mounted() {
    this.$nextTick(function() {
      this.initChart();
      this.drawChart();
    });
  },
  watch: {
    data: {
      handler() {
        this.updateData();
      }
    }
  },
  computed: {
    MaxGroupTick() {
      if (this.data.length === 0) return 0;
      const season1 = this.data.slice(0, 3).reduce((total, item) => {
        return total + item.y;
      }, 0);
      const season2 = this.data.slice(3, 6).reduce((total, item) => {
        return total + item.y;
      }, 0);
      const season3 = this.data.slice(6, 9).reduce((total, item) => {
        return total + item.y;
      }, 0);
      const season4 = this.data.slice(9, 12).reduce((total, item) => {
        return total + item.y;
      }, 0);
      return Math.max(season1, season2, season3, season4);
    }
  },
  methods: {
    getTicks(scale) {
      const { min, max, tickCount } = scale;
      let myMax = max;
      let avg = (myMax - min) / tickCount;
      avg = Math.ceil(avg);
      const digit = Math.pow(10, avg.toString().length - 1);
      avg = Math.ceil(avg / digit) * digit;
      if (myMax === 0 && min === 0) {
        scale.max = 1;
        return [0, 1];
      }
      if (myMax < -Number.MAX_VALUE) {
        return [''];
      } else {
        myMax = avg * tickCount;
      }
      const ticks = [];
      const toFixedNumber = avg.toString().split('.')[1] ? avg.toString().split('.')[1].length : 0;
      for (let i = min; i < myMax; i += avg) {
        ticks.push(i.toFixed(toFixedNumber));
      }
      ticks.push(myMax.toFixed(toFixedNumber));
      scale.max = myMax;
      return ticks;
    },
    initChart() {
      const ref = this.$refs.chart;
      const ratio = window.ratio || 1;
      this.chart = new Chart({
        container: ref,
        width: ref.clientWidth,
        height: ref.clientHeight,
        appendPadding: [22 * ratio, 0, 0, 5 * ratio]
      });
    },
    drawChart() {
      const ref = this.$refs.chart;
      const ratio = window.ratio || 1;
      const x = this.x;
      const y = this.y;
      const s = this.s;
      // 自定义交互
      registerInteraction('legend-visible-filter', {
        showEnable: [
          { trigger: 'legend-item:mouseenter', action: 'cursor:pointer' },
          { trigger: 'legend-item:mouseleave', action: 'cursor:default' }
        ],
        start: [
          { trigger: 'legend-item:click', action: 'list-unchecked:toggle' },
          { trigger: 'legend-item:click', action: 'element-filter:filter' }
        ]
      });
      this.chart.data(this.data);
      this.chart.scale(y, {
        min: 0,
        max: this.MaxGroupTick,
        tickCount: 4,
        tickMethod: this.getTicks
      });
      // 提示框
      this.chart.tooltip({
        shared: true,
        showMarkers: false,
        title: title => {
          if (/^(\d{4})-(\d{1,2})月$/.test(title)) {
            const arr = title.split('-');
            const month = arr[1].length === 2 ? 0 + arr[1] : arr[1];
            return arr[0] + '-' + month;
          }
          return title;
        },
        customItems: items => {
          items.forEach(item => {
            if (/^(\d{4})-(\d{2})$/.test(item.name)) {
              let month = item.name.split('-')[1];
              if (month[0] === '0') month = month.replace('0', '');
              item.name = month + '月';
            }
            item.value = this.$options.filters.dataFormat(Number(item.value)) + this.unit;
          });
          return items;
        },
        itemTpl: `
          <li class="g2-tooltip-list-item">
            <span class="g2-tooltip-marker" style="background-color: {color}"></span>
            <span class="g2-tooltip-name">{name}</span>：<span class="g2-tooltip-value">{value}</span>
          </li>
        `,
        domStyles: {
          'g2-tooltip': {
            borderRadius: '0.25rem',
            backgroundColor: 'rgba(0, 0, 0, 0.5)',
            boxShadow: 'none',
            padding: '.3125rem .5rem',
            whiteSpace: 'nowrap'
          },
          'g2-tooltip-title': {
            fontFamily: 'Roboto-regular',
            fontSize: '0.75rem',
            textAlign: 'left',
            color: '#A6ADB7',
            marginBottom: '.625rem'
          },
          'g2-tooltip-list-item': {
            display: 'flex',
            alignItems: 'center',
            fontSize: '0.75rem',
            color: '#D9D9D9',
            marginTop: '.625rem'
          },
          'g2-tooltip-marker': {
            margin: '0',
            width: '.375rem',
            height: '.375rem'
          },
          'g2-tooltip-name': {
            marginLeft: '0.3125rem'
          },
          'g2-tooltip-value': {
            marginLeft: '0.3125rem'
          }
        }
      });
      // x轴
      this.chart.axis(x, {
        label: {
          style: {
            fill: '#A6ADB7',
            fontSize: 12 * ratio,
            fontFamily: 'Helvetica-regular'
          },
          offset: 6 * ratio,
          formatter: text => xFormat(text),
          autoHide: false
        },
        line: {
          style: {
            stroke: '#FFFFFF',
            strokeOpacity: 0.4,
            lineWidth: 1 * ratio
          }
        },
        tickLine: null
      });
      // y轴
      this.chart.axis(y, {
        label: {
          style: {
            fill: '#8E8E8E',
            fontSize: 12 * ratio,
            fontFamily: 'Helvetica-regular'
          },
          offset: 8 * ratio
        },
        grid: {
          line: {
            style: {
              stroke: '#FFFFFF',
              opacity: 0.3,
              lineWidth: 1 * ratio,
              lineDash: [3 * ratio, 3 * ratio]
            }
          }
        }
      });
      // 图例
      this.chart.legend(false);
      // 修改图例交互
      this.chart.removeInteraction('legend-filter');
      this.chart.interaction('legend-visible-filter');
      // active-region
      this.chart.interaction('active-region');
      this.chart
        .interval()
        .position(`${x}*${y}`)
        .size(15 * ratio)
        .adjust([
          {
            type: 'stack',
            marginRatio: 0.5,
            reverseOrder: false
          }
        ])
        .color(s, this.color)
        .animate({
          appear: {
            delay: 0,
            duration: 2000
          }
        });
      this.chart.render();
      const right =
        -ref.clientWidth -
        this.offsetX +
        this.chart.autoPadding.right +
        this.chart.autoPadding.left -
        8 * ratio -
        computeFontSize(this.unit, 12 * ratio);
      // 单位标注
      this.chart.annotation().text({
        content: this.unit,
        position: ['end', 'start'],
        style: {
          fill: '#8E8E8E',
          fontSize: 12 * ratio,
          fontFamily: 'Helvetica-regular'
        },
        background: {
          padding: 2 * ratio
        },
        offsetY: -ref.clientHeight + 27 * ratio,
        offsetX: right
      });
      this.chart.render();
    },
    // 数据更新
    updateData() {
      this.chart.clear();
      this.drawChart();
    }
  },
  beforeDestroy() {
    this.chart?.destroy();
  }
};
</script>
<style lang="scss" scoped></style>
